import pandas as pd
import numpy as np


def calculate_entropy_topsis(data):
    """
    使用熵权法计算TOPSIS的权重和评分。
    """
    # 提取数据
    mean_return = data["Mean Return"]
    std_dev = data["Standard Deviation"]
    sharpe_ratio = data["Sharpe Ratio"]

    # 构建决策矩阵
    X = np.vstack((mean_return, std_dev, sharpe_ratio)).T

    # 标准化决策矩阵
    R = X / np.sqrt(np.sum(X**2, axis=0))

    # 计算熵值
    P = R / np.sum(R, axis=0)
    entropy = -np.sum(P * np.log(P + 1e-9), axis=0) / np.log(len(X))

    # 计算权重
    weights = (1 - entropy) / np.sum(1 - entropy)

    # 加权标准化决策矩阵
    Z = R * weights

    # 确定正理想解和负理想解
    Z_max = np.zeros(Z.shape[1])
    Z_min = np.zeros(Z.shape[1])

    # 设置正理想解和负理想解
    for i in range(Z.shape[1]):
        if i == 0 or i == 2:  # Mean Return and Sharpe Ratio (越大越好)
            Z_max[i] = np.max(Z[:, i])
            Z_min[i] = np.min(Z[:, i])
        else:  # Standard Deviation (越小越好)
            Z_max[i] = np.min(Z[:, i])
            Z_min[i] = np.max(Z[:, i])

    # 计算与正理想解和负理想解的距离
    S_plus = np.sqrt(np.sum((Z - Z_max) ** 2, axis=1))
    S_minus = np.sqrt(np.sum((Z - Z_min) ** 2, axis=1))

    # 计算相对接近度
    C = S_minus / (S_plus + S_minus)

    # 将相对接近度作为新列添加到结果数据框中
    data["总得分"] = C

    return data


def 数据分析():
    """
    数据分析主函数，计算模型的平均收益、标准差和夏普比率，并使用熵权法优化评价模型。
    """
    # 读取数据
    df = pd.read_csv("model_results.csv", index_col=0)
    df = df.apply(pd.to_numeric, errors="coerce")

    # 计算平均收益和标准差
    mean_returns = df.mean()
    std_returns = df.std()

    # 假设无风险收益率为3%
    risk_free_rate = 0.03

    # 计算夏普比率
    sharpe_ratios = (mean_returns - risk_free_rate) / std_returns

    # 整理到一个新的数据框中
    evaluation_metrics = pd.DataFrame(
        {
            "Mean Return": mean_returns,
            "Standard Deviation": std_returns,
            "Sharpe Ratio": sharpe_ratios,
        }
    )

    # 使用熵权法优化评价模型
    result = calculate_entropy_topsis(evaluation_metrics)

    # 将结果保存到CSV文件中，避免科学计数法
    result.to_csv("评价50个模型.csv", float_format="%.4f", index=True)

    return result


# 执行数据分析
result = 数据分析()

# 打印结果
print(result)
